#ifndef __tenacitas_crosswords1_concept_organizer_tester_h__
#define __tenacitas_crosswords1_concept_organizer_tester_h__

#include <iostream>
#include <cstdint>
#include <string>

#include "runtest.h"

#include <tenacitas.crosswords.core/organizer.h>
#include <tenacitas.return_code.core/rc.h>

namespace tenacitas {
    namespace crosswords {
        namespace concept {

            class organizer_tester {
            private:
                struct supplier {
                    typedef concept::organizer<supplier> organizer;
                    typedef std::string text;
                };

                typedef concept::layouts<supplier> layouts;
                typedef typename layouts::layout_index layout_index;
                typedef concept::word<supplier> word;
                typedef supplier::text text;
                typedef typename text::value_type letter;
                typedef supplier::organizer organizer;
                typedef concept::coordinate<supplier> coordinate;
                typedef concept::coordinates<supplier> coordinates;
                typedef typename coordinates::index coordinate_index;

                static void print(const layouts & p_layouts) {
                    coordinate _coord = p_layouts.greatest();
                    int16_t _num_lines = static_cast<int16_t>(_coord.get_line())
                        + 1;
                    int16_t _num_cols = static_cast<int16_t>(_coord.get_column())
                        + 1;

                    std::cerr << "num lines = " << _num_lines << ", num cols = "
                              << _num_cols << std::endl;
                    
                    
                    letter _matrix[_num_lines][_num_cols];
                    for (int16_t _l = 0; _l < _num_lines; ++_l) {
                        for (int16_t _c = 0; _c < _num_cols; ++_c) {
                            _matrix[_l][_c] = letter(' ');
                        }
                    }

                    layout_index _size_layouts = p_layouts.get_size();
                    for (layout_index _lay_index = 0;
                         _lay_index < _size_layouts;
                         ++_lay_index) {
                        const coordinates & _coords =
                            p_layouts[_lay_index].get_coordinates();
                        coordinate_index _size_coords = _coords.get_size();
                        for (coordinate_index _coord_index = 0;
                             _coord_index < _size_coords;
                             ++_coord_index) {
                            int16_t _line =
                                static_cast<int16_t>(_coords[_coord_index].get_line());
                            int16_t _col =
                                static_cast<int16_t>(_coords[_coord_index].get_column()); 
                            _matrix[_line][_col] = _coords[_coord_index].get_letter();
                        }
                    }

                    std::cerr << "   ";
                    for (int16_t _c = 0; _c < _num_cols; ++_c) {
                        // std::cerr.width(3);
                        // std::cerr.fill(' ');
                        if (_c < 10) {
                            std::cerr << "  " << _c << " ";
                        }
                        else {
                            std::cerr << " " << _c << " ";
                        }
                        
                    }
                    std::cerr << std::endl;
                    
                    
                    for (int16_t _l = 0; _l < _num_lines; ++_l) {
                        std::cerr.width(2);
                        std::cerr.fill(' ');
                        std::cerr << _l << " | ";
                        for (int16_t _c = 0; _c < _num_cols; ++_c) {
                            std::cerr << _matrix[_l][_c] << " | ";
                        }
                        std::cerr << std::endl;
                    }

                    

                    // std::string _sep((std::string(" | ").size() + 1 ) *
                    //                  _num_cols, '-'); 

                    // for (int16_t _l = 0; _l < _num_lines; ++_l) {
                    //     for (int16_t _c = 0; _l < _num_cols; ++_c) {
                    //         std::cerr << " | " << _matrix[_l][_c];
                    //     }
                    //     std::cerr << " | " << std::endl;
                    // }
                }
                
    

                static bool test1() {
                    std::cerr << "\n+++ organizer_tester::test1" << std::endl;

                    word _w1(text("abacaxi"),
                             text("fruta tropical com coroa"),
                             word::category::easy);
                    
                    layouts _layouts;

                    _layouts.add(_w1);
                    _layouts.print(std::cerr);

                    organizer _org;
                    
                    rc_t _rc = _org(_layouts);

                    _layouts.print(std::cerr);

                    print(_layouts);

                    return (_rc);
                    
                }

                static bool test2() {
                    std::cerr << "\n+++ organizer_tester::test2" << std::endl;

                    word _w1(text("abacaxi"),
                             text("fruta tropical com coroa"),
                             word::category::easy);

                    word _w2(text("xixi"),
                             text("sinonimo de urina"),
                             word::category::easy);
                    
                    
                    layouts _layouts;

                    _layouts.add(_w1);
                    _layouts.add(_w2);
                    _layouts.print(std::cerr);

                    organizer _org;
                    
                    rc_t _rc = _org(_layouts);

                    _layouts.print(std::cerr);

                    print(_layouts);

                    return (_rc);
                    
                }

                static bool test3() {
                    std::cerr << "\n+++ organizer_tester::test3" << std::endl;

                    word _w1(text("abacaxi"),
                             text("fruta tropical com coroa"),
                             word::category::easy);

                    word _w2(text("xixi"),
                             text("sinonimo de urina"),
                             word::category::easy);
                    
                    word _w3(text("bau"),
                             text("caixa grande para guardar coisas"),
                             word::category::easy);
                    
                    layouts _layouts;

                    _layouts.add(_w1);
                    _layouts.add(_w2);
                    _layouts.add(_w3);
                    _layouts.print(std::cerr);

                    organizer _org;
                    
                    rc_t _rc = _org(_layouts);

                    _layouts.print(std::cerr);

                    print(_layouts);

                    return (_rc);
                    
                }
                
                static bool test4() {
                    std::cerr << "\n+++ organizer_tester::test4" << std::endl;

                    word _w1(text("abacaxi"),
                             text("fruta tropical com coroa"),
                             word::category::easy);

                    word _w2(text("xixi"),
                             text("sinonimo de urina"),
                             word::category::easy);
                    
                    word _w3(text("bau"),
                             text("caixa grande para guardar coisas"),
                             word::category::easy);
                    
                    word _w4(text("velha"),
                             text("coisa antiga "),
                             word::category::easy);

                    layouts _layouts;

                    _layouts.add(_w1);
                    _layouts.add(_w2);
                    _layouts.add(_w3);
                    _layouts.add(_w4);
                    _layouts.print(std::cerr);

                    organizer _org;
                    
                    rc_t _rc = _org(_layouts);

                    _layouts.print(std::cerr);

                    print(_layouts);

                    return (_rc);
                    
                }

                static bool test5() {
                    std::cerr << "\n+++ organizer_tester::test5" << std::endl;

                    word _w1(text("abacaxi"),
                             text("fruta tropical com coroa"),
                             word::category::easy);

                    word _w2(text("xixi"),
                             text("sinonimo de urina"),
                             word::category::easy);
                    
                    word _w3(text("bau"),
                             text("caixa grande para guardar coisas"),
                             word::category::easy);
                    
                    word _w4(text("velha"),
                             text("coisa antiga "),
                             word::category::easy);

                    layouts _layouts;

                    _layouts.add(_w1);
                    _layouts.add(_w2);
                    _layouts.add(_w3);
                    _layouts.add(_w4);
                    _layouts.add(word(text("queijo"),
                                      text("derivado do leite"),
                                      word::easy));
                    _layouts.add(word(text("quilometro"),
                                      text("medida de distancia"),
                                      word::easy));
                    _layouts.add(word(text("viajem"),
                                      text("ir para outro pais"),
                                      word::easy));
                    _layouts.add(word(text("flamengo"),
                                      text("maior clube do Brasil"),
                                      word::easy));
                    _layouts.add(word(text("rouxinol"),
                                      text("tipo de passaro"),
                                      word::easy));
                    _layouts.add(word(text("limpeza"),
                                      text("contrario de sujeira"),
                                      word::easy));
                    _layouts.add(word(text("paz"),
                                      text("contrario de guerra"),
                                      word::easy));
                    _layouts.add(word(text("wolverine"),
                                      text("tipo de texugo"),
                                      word::easy));
                    _layouts.add(word(text("parafuso"),
                                      text(""),
                                      word::easy));
                    _layouts.print(std::cerr);

                    organizer _org;
                    
                    rc_t _rc = _org(_layouts);

                    _layouts.print(std::cerr);

                    print(_layouts);

                    return (_rc);
                    
                }
                
                static bool test6() {
                    std::cerr << "\n+++ organizer_tester::test6" << std::endl;

                    layouts _layouts;

                    _layouts.add(word(text("thor"),
                                      text(""),
                                      word::easy));
                    _layouts.add(word(text("hulk"),
                                      text(""),
                                      word::easy));
                    _layouts.add(word(text("visao"),
                                      text(""),
                                      word::easy));
                    _layouts.add(word(text("viuva"),
                                      text(""),
                                      word::easy));
                    _layouts.add(word(text("ferro"),
                                      text(""),
                                      word::easy));
                    _layouts.add(word(text("america"),
                                      text(""),
                                      word::easy));
                    _layouts.add(word(text("arqueiro"),
                                      text(""),
                                      word::easy));
                    _layouts.add(word(text("escarlate"),
                                      text(""),
                                      word::easy));
                    _layouts.add(word(text("mercurio"),
                                      text(""),
                                      word::easy));
                    _layouts.print(std::cerr);

                    organizer _org;
                    
                    rc_t _rc = _org(_layouts);

                    _layouts.print(std::cerr);

                    print(_layouts);

                    return (_rc);
                    
                }

                static bool test7() {
                    std::cerr << "\n+++ organizer_tester::test7" << std::endl;

                    layouts _layouts;

                    _layouts.add(word(text("agravado"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("mambo"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("cume"),
                                      text(""),
                                      word::easy));
                    
                    _layouts.add(word(text("trineto"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("wilde"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("gole"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("rixa"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("liso"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("imortal"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("ag"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("martins"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("crescido"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("socar"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("esgalha"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("temor"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("azul"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("tres"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("harioldo"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("dom"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("ferrugem"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("pretagil"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("af"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("sereia"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("item"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("titanic"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("bage"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("zero"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("oronasal"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("atrasados"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("gr"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("mambo"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("rir"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("mambo"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("animal"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("vexar"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("atar"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("do"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("missa"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("alo"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("md"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("beirar"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("me"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("gosto"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("corcel"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("ultimo"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("meado"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("loro"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("gozo"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("ete"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("cumprir"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("reto"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("feia"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("tetano"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("terra"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("ir"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("lisergico"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("wingsuit"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("gleba"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("lhe"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("mas"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("chama"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("ga"),
                                      text(""),
                                      word::easy));

                    _layouts.add(word(text("fiel"),
                                      text(""),
                                      word::easy));

                    organizer _org;
                    
                    rc_t _rc = _org(_layouts);

                    if (_rc) {
                        print(_layouts);
                    }

                    return _rc;
                    
                }
                
                    

            public:
                static void run() {
                    runtest(organizer_tester::test1());
                    runtest(organizer_tester::test2());
                    runtest(organizer_tester::test3());
                    runtest(organizer_tester::test4());
                    runtest(organizer_tester::test5());
                    runtest(organizer_tester::test6());
                    runtest(organizer_tester::test7());
                }

            };

        }
    }
}

#endif
